package com.cy.dda.comm.interceptor;

import java.util.List;
import java.util.Optional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.cy.dda.comm.constant.Constants;
import com.cy.dda.comm.exception.MsgException;
import com.cy.dda.comm.utils.CommonUtils;
import com.cy.dda.model.domain.rule.Menu;
import com.cy.dda.model.dto.rule.ManagerLoginDTO;
import com.cy.dda.service.rule.RuleService;

import lombok.extern.slf4j.Slf4j;

/**
 * 后台管理员拦截器
 *
 * @author: tanyilin
 * @create: 2018年10月29日 上午10:26:22
 */
@Slf4j
@Component
public class AdminLoginInterceptor implements HandlerInterceptor{

	@Autowired
	private RedisTemplate redisTemplate;
	@Autowired
    private RuleService ruleService;
	
	private AntPathMatcher antPathMatcher = new AntPathMatcher();

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object)
			throws Exception {
		// 从头部获取token
		String token = request.getHeader(Constants.TOKEN);
		if(CommonUtils.isEmpty(token)) {
			throw new MsgException("未登录", -1000);
		}
		String key = Constants.ADMIN_LOGIN_KEY.concat(token);
		// 查询redis里已登录的管理员账户信息是否存在
		Object obj = redisTemplate.opsForValue().get(key);
		if(CommonUtils.isEmpty(obj)) {
			throw new MsgException("登录已失效", -1000);
		}
		//重新设置过期时间
		redisTemplate.expire(key, Constants.LOGIN_TIME, Constants.LOGIN_TIME_UNIT);
		
		//判断该用户是否有当前路径访问权限
		ManagerLoginDTO managerLoginDTO = (ManagerLoginDTO) obj;
		boolean hasRole = hasRole(request, managerLoginDTO);
		if(!hasRole) {
			throw new MsgException("权限不足");
		}

		return true;
	}

	private boolean hasRole(HttpServletRequest httpServletRequest, ManagerLoginDTO managerLoginDTO) {
		
		if(Constants.ADMININTRATOR.equals(managerLoginDTO.getRoleId())) {
			//超级管理员，拥有全部权限
			return true;
		}
		
		//取得 uri
		String uri = httpServletRequest.getRequestURI();
		
		//缓存中的全部菜单
		List<Menu> menus = ruleService.selectAllMenuInCache();
		Optional<Menu> optional = menus.stream()
				.filter(m -> StringUtils.hasLength(m.getPattern()))
				.filter(m -> antPathMatcher.match(m.getPattern(), uri)).findFirst();
		
		if(!optional.isPresent()) {
			//如果uri未配置菜单，则返回true
            return true;
		}
		
		//该路径菜单
        Menu menu = optional.get();
		//用户角色
        Long roleId = managerLoginDTO.getRoleId();
        //该角色拥有的菜单权限
        List<Long> menuIds = ruleService.selectAllMenuByRoleIdInCache(roleId);
        
        if(menuIds.isEmpty()) {
        	return false;
        }
        
        return menuIds.stream().anyMatch(id -> id.equals(menu.getId()));
	}
	
	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		
	}
}
